#include <iostream>
#include <cassert>
#include "vector.hpp"

// 一个辅助函数，用于打印 vector 内容
template <typename T>
void print_vector(const wk::vector<T>& vec, const std::string& name) {
    std::cout << name << " (size=" << vec.size() << ", cap=" << vec.capacity() << "): ";
    for (const auto& item : vec) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

void test_constructors() {
    std::cout << "\n--- Testing Constructors ---\n";
    wk::vector<int> v1;
    print_vector(v1, "v1 (default)");

    wk::vector<int> v2(5, 100);
    print_vector(v2, "v2 (fill)");

    wk::vector<int> v3 = {1, 2, 3, 4, 5};
    print_vector(v3, "v3 (initializer_list)");

    wk::vector<int> v4(v3);
    print_vector(v4, "v4 (copy of v3)");
    assert(v3.size() == v4.size());

    wk::vector<int> v5(std::move(v4));
    print_vector(v5, "v5 (move of v4)");
    print_vector(v4, "v4 (after move)");
    assert(v4.size() == 0);
    assert(v4.begin() == nullptr);

    wk::vector<int> v6(v5.begin() + 1, v5.end() - 1);
    print_vector(v6, "v6 (iterator range)");
    assert(v6.size() == 3);
    assert(v6[0] == 2);
}

void test_assignment() {
    std::cout << "\n--- Testing Assignment ---\n";
    wk::vector<int> v1 = {1, 2, 3};
    wk::vector<int> v2 = {4, 5, 6, 7, 8};
    print_vector(v1, "v1 (before copy assign)");
    print_vector(v2, "v2 (before copy assign)");
    v1 = v2;
    print_vector(v1, "v1 (after copy assign)");
    print_vector(v2, "v2 (after copy assign)");
    assert(v1.size() == v2.size());

    wk::vector<int> v3;
    v3 = std::move(v2);
    print_vector(v3, "v3 (after move assign)");
    print_vector(v2, "v2 (after move)");
    assert(v2.size() == 0);
}

void test_push_pop() {
    std::cout << "\n--- Testing Push/Pop Back ---\n";
    wk::vector<int> v;
    print_vector(v, "v (initial)");
    v.push_back(10);
    print_vector(v, "v (after push_back 10)");
    v.push_back(20);
    print_vector(v, "v (after push_back 20)");
    assert(v.size() == 2 && v[0] == 10 && v[1] == 20);
    
    v.pop_back();
    print_vector(v, "v (after pop_back)");
    assert(v.size() == 1 && v.front() == 10);

    v.pop_back();
    print_vector(v, "v (after pop_back)");
    assert(v.empty());

    // Test reserve
    wk::vector<int> v2;
    v2.reserve(10);
    assert(v2.capacity() >= 10);
    size_t cap_before = v2.capacity();
    v2.push_back(1);
    v2.push_back(2);
    assert(v2.capacity() == cap_before); // Capacity should not change
    print_vector(v2, "v2 (with reserve)");
}

void test_insert() {
    std::cout << "\n--- Testing Insert ---\n";
    wk::vector<int> v = {10, 20, 30};
    
    // Insert at beginning
    v.insert(v.begin(), 5);
    print_vector(v, "v (insert at begin)");
    assert(v.size() == 4 && v[0] == 5);

    // Insert in middle
    v.insert(v.begin() + 2, 15);
    print_vector(v, "v (insert in middle)");
    assert(v.size() == 5 && v[2] == 15);

    // Insert at end
    v.insert(v.end(), 35);
    print_vector(v, "v (insert at end)");
    assert(v.size() == 6 && v.back() == 35);

    // Insert range
    int arr[] = {100, 200, 300};
    v.insert(v.begin() + 1, arr, arr + 3);
    print_vector(v, "v (insert range)");
    assert(v.size() == 9 && v[1] == 100 && v[2] == 200 && v[3] == 300);
}

void test_erase() {
    std::cout << "\n--- Testing Erase ---\n";
    wk::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // Erase from middle
    v.erase(v.begin() + 2); // erase 3
    print_vector(v, "v (erase from middle)");
    assert(v.size() == 9 && v[2] == 4);

    // Erase from beginning
    v.erase(v.begin()); // erase 1
    print_vector(v, "v (erase from beginning)");
    assert(v.size() == 8 && v.front() == 2);

    // Erase from end
    v.erase(v.end() - 1); // erase 10
    print_vector(v, "v (erase from end)");
    assert(v.size() == 7 && v.back() == 9);

    // Erase range
    v.erase(v.begin() + 1, v.begin() + 4); // erase 4, 5, 6
    print_vector(v, "v (erase range)");
    assert(v.size() == 4 && v[0] == 2 && v[1] == 7 && v[2] == 8 && v[3] == 9);

    // Erase all
    v.erase(v.begin(), v.end());
    print_vector(v, "v (erase all)");
    assert(v.empty());
}

void test_access() {
    std::cout << "\n--- Testing Accessors ---\n";
    wk::vector<int> v = {10, 20, 30};
    assert(v.front() == 10);
    assert(v.back() == 30);
    assert(v[1] == 20);
    assert(v.at(2) == 30);

    try {
        v.at(3); // Should throw
    } catch (const std::out_of_range& e) {
        std::cout << "Caught expected exception: " << e.what() << std::endl;
    }
}

void test_clear() {
    std::cout << "\n--- Testing Clear ---\n";
    wk::vector<int> v = {1, 2, 3, 4, 5};
    size_t cap = v.capacity();
    print_vector(v, "v (before clear)");
    v.clear();
    print_vector(v, "v (after clear)");
    assert(v.empty());
    assert(v.capacity() == cap); // Capacity should not change
}


int main() {
    test_constructors();
    test_assignment();
    test_access();
    test_push_pop();
    test_insert();
    test_erase();
    test_clear();

    std::cout << "\nAll tests passed!\n";
    return 0;
}
